1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "oox/core/relationshandler.hxx"
25 
26 #include <rtl/ustrbuf.hxx>
27 #include "oox/helper/attributelist.hxx"
28 
29 namespace oox {
30 namespace core {
31 
32 // ============================================================================
33 
34 using namespace ::com::sun::star::uno;
35 using namespace ::com::sun::star::xml::sax;
36 
37 using ::rtl::OUString;
38 using ::rtl::OUStringBuffer;
39 
40 // ============================================================================
41 
42 namespace {
43 
44 /*  Build path to relations file from passed fragment path, e.g.:
45         'path/path/file.xml'    -> 'path/path/_rels/file.xml.rels'
46         'file.xml'              -> '_rels/file.xml.rels'
47         ''                      -> '_rels/.rels'
48  */
49 OUString lclGetRelationsPath( const OUString& rFragmentPath )
50 {
51     sal_Int32 nPathLen = ::std::max< sal_Int32 >( rFragmentPath.lastIndexOf( '/' ) + 1, 0 );
52     return
53         OUStringBuffer( rFragmentPath.copy( 0, nPathLen ) ).    // file path including slash
54         appendAscii( "_rels/" ).                                // additional '_rels/' path
55         append( rFragmentPath.copy( nPathLen ) ).               // file name after path
56         appendAscii( ".rels" ).                                 // '.rels' suffix
57         makeStringAndClear();
58 }
59 
60 } // namespace
61 
62 // ============================================================================
63 
64 RelationsFragment::RelationsFragment( XmlFilterBase& rFilter, RelationsRef xRelations ) :
65     FragmentHandler( rFilter, lclGetRelationsPath( xRelations->getFragmentPath() ), xRelations ),
66     mxRelations( xRelations )
67 {
68 }
69 
70 Reference< XFastContextHandler > RelationsFragment::createFastChildContext(
71         sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw (SAXException, RuntimeException)
72 {
73     Reference< XFastContextHandler > xRet;
74     AttributeList aAttribs( rxAttribs );
75     switch( nElement )
76     {
77         case PR_TOKEN( Relationship ):
78         {
79             Relation aRelation;
80             aRelation.maId     = aAttribs.getString( XML_Id, OUString() );
81             aRelation.maType   = aAttribs.getString( XML_Type, OUString() );
82             aRelation.maTarget = aAttribs.getString( XML_Target, OUString() );
83             if( (aRelation.maId.getLength() > 0) && (aRelation.maType.getLength() > 0) && (aRelation.maTarget.getLength() > 0) )
84             {
85                 sal_Int32 nTargetMode = aAttribs.getToken( XML_TargetMode, XML_Internal );
86                 OSL_ENSURE( (nTargetMode == XML_Internal) || (nTargetMode == XML_External),
87                     "RelationsFragment::createFastChildContext - unexpected target mode, assuming external" );
88                 aRelation.mbExternal = nTargetMode != XML_Internal;
89 
90                 OSL_ENSURE( mxRelations->count( aRelation.maId ) == 0,
91                     "RelationsFragment::createFastChildContext - relation identifier exists already" );
92                 mxRelations->insert( Relations::value_type( aRelation.maId, aRelation ) );
93             }
94         }
95         break;
96         case PR_TOKEN( Relationships ):
97             xRet = getFastContextHandler();
98         break;
99     }
100     return xRet;
101 }
102 
103 // ============================================================================
104 
105 } // namespace core
106 } // namespace oox
107