View Javadoc
1   package org.apache.maven.index.reader;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.index.reader.Record.Type;
23  
24  import java.util.HashMap;
25  import java.util.Map;
26  
27  import static org.apache.maven.index.reader.Utils.FIELD_SEPARATOR;
28  import static org.apache.maven.index.reader.Utils.INFO;
29  import static org.apache.maven.index.reader.Utils.UINFO;
30  import static org.apache.maven.index.reader.Utils.nvl;
31  
32  /**
33   * Maven 2 Index record transformer, that transforms {@link Record}s into "native" Maven Indexer records.
34   *
35   * @since 5.1.2
36   */
37  public class RecordCompactor
38  {
39      /**
40       * Compacts {@link Record} into low level MI record with all the encoded fields as physically present in MI binary
41       * chunk.
42       */
43      public Map<String, String> apply( final Record record )
44      {
45          if ( Type.DESCRIPTOR == record.getType() )
46          {
47              return compactDescriptor( record );
48          }
49          else if ( Type.ALL_GROUPS == record.getType() )
50          {
51              return compactAllGroups( record );
52          }
53          else if ( Type.ROOT_GROUPS == record.getType() )
54          {
55              return compactRootGroups( record );
56          }
57          else if ( Type.ARTIFACT_REMOVE == record.getType() )
58          {
59              return compactDeletedArtifact( record );
60          }
61          else if ( Type.ARTIFACT_ADD == record.getType() )
62          {
63              return compactAddedArtifact( record );
64          }
65          else
66          {
67              throw new IllegalArgumentException( "Unknown record: " + record );
68          }
69      }
70  
71      private static Map<String, String> compactDescriptor( final Record record )
72      {
73          final Map<String, String> result = new HashMap<>();
74          result.put( "DESCRIPTOR", "NexusIndex" );
75          result.put( "IDXINFO", "1.0|" + record.get( Record.REPOSITORY_ID ) );
76          return result;
77      }
78  
79      private static Map<String, String> compactAllGroups( final Record record )
80      {
81          final Map<String, String> result = new HashMap<>();
82          result.put( "allGroups", "allGroups" );
83          putIfNotNullAsStringArray( record.get( Record.ALL_GROUPS ), result, "allGroupsList" );
84          return result;
85      }
86  
87      private static Map<String, String> compactRootGroups( final Record record )
88      {
89          final Map<String, String> result = new HashMap<>();
90          result.put( "rootGroups", "allGroups" );
91          putIfNotNullAsStringArray( record.get( Record.ROOT_GROUPS ), result, "rootGroupsList" );
92          return result;
93      }
94  
95      private static Map<String, String> compactDeletedArtifact( final Record record )
96      {
97          final Map<String, String> result = new HashMap<>();
98          putIfNotNullTS( record.get( Record.REC_MODIFIED ), result, "m" );
99          result.put( "del", compactUinfo( record ) );
100         return result;
101     }
102 
103     /**
104      * Expands the "encoded" Maven Indexer record by splitting the synthetic fields and applying expanded field naming.
105      */
106     private static Map<String, String> compactAddedArtifact( final Record record )
107     {
108         final Map<String, String> result = new HashMap<>();
109 
110         // Minimal
111         result.put( UINFO, compactUinfo( record ) );
112 
113         String info = nvl( record.get( Record.PACKAGING ) ) + FIELD_SEPARATOR + record.get(
114                 Record.FILE_MODIFIED ) + FIELD_SEPARATOR + record.get(
115                 Record.FILE_SIZE ) + FIELD_SEPARATOR + ( record.get(
116                 Record.HAS_SOURCES ) ? "1" : "0" ) + FIELD_SEPARATOR + ( record.get(
117                 Record.HAS_JAVADOC ) ? "1" : "0" ) + FIELD_SEPARATOR + ( record.get(
118                 Record.HAS_SIGNATURE ) ? "1" : "0" ) + FIELD_SEPARATOR + nvl( record.get( Record.FILE_EXTENSION ) );
119         result.put( INFO, info );
120 
121         putIfNotNullTS( record.get( Record.REC_MODIFIED ), result, "m" );
122         putIfNotNull( record.get( Record.NAME ), result, "n" );
123         putIfNotNull( record.get( Record.DESCRIPTION ), result, "d" );
124         putIfNotNull( record.get( Record.SHA1 ), result, "1" );
125 
126         // Jar file contents (optional)
127         putIfNotNullAsStringArray( record.get( Record.CLASSNAMES ), result, "classnames" );
128 
129         // Maven Plugin (optional)
130         putIfNotNull( record.get( Record.PLUGIN_PREFIX ), result, "px" );
131         putIfNotNullAsStringArray( record.get( Record.PLUGIN_GOALS ), result, "gx" );
132 
133         // OSGi (optional)
134         putIfNotNull( record.get( Record.OSGI_BUNDLE_SYMBOLIC_NAME ), result, "Bundle-SymbolicName" );
135         putIfNotNull( record.get( Record.OSGI_BUNDLE_VERSION ), result, "Bundle-Version" );
136         putIfNotNull( record.get( Record.OSGI_EXPORT_PACKAGE ), result, "Export-Package" );
137         putIfNotNull( record.get( Record.OSGI_EXPORT_SERVICE ), result, "Export-Service" );
138         putIfNotNull( record.get( Record.OSGI_BUNDLE_DESCRIPTION ), result, "Bundle-Description" );
139         putIfNotNull( record.get( Record.OSGI_BUNDLE_NAME ), result, "Bundle-Name" );
140         putIfNotNull( record.get( Record.OSGI_BUNDLE_LICENSE ), result, "Bundle-License" );
141         putIfNotNull( record.get( Record.OSGI_EXPORT_DOCURL ), result, "Bundle-DocURL" );
142         putIfNotNull( record.get( Record.OSGI_IMPORT_PACKAGE ), result, "Import-Package" );
143         putIfNotNull( record.get( Record.OSGI_REQUIRE_BUNDLE ), result, "Require-Bundle" );
144         putIfNotNull( record.get( Record.OSGI_PROVIDE_CAPABILITY ), result, "Provide-Capability" );
145         putIfNotNull( record.get( Record.OSGI_REQUIRE_CAPABILITY ), result, "Require-Capability" );
146         putIfNotNull( record.get( Record.OSGI_FRAGMENT_HOST ), result, "Fragment-Host" );
147         putIfNotNull( record.get( Record.OSGI_BREE ), result, "Bundle-RequiredExecutionEnvironment" );
148         putIfNotNull( record.get( Record.SHA_256 ), result, "sha256" );
149 
150         return result;
151     }
152 
153     /**
154      * Creates UINFO synthetic field.
155      */
156     private static String compactUinfo( final Record record )
157     {
158         final String classifier = record.get( Record.CLASSIFIER );
159         StringBuilder sb = new StringBuilder();
160         sb.append( record.get( Record.GROUP_ID ) ).append( FIELD_SEPARATOR ).append(
161             record.get( Record.ARTIFACT_ID ) ).append( FIELD_SEPARATOR ).append( record.get( Record.VERSION ) ).append(
162             FIELD_SEPARATOR ).append( nvl( classifier ) );
163         if ( classifier != null )
164         {
165             sb.append( FIELD_SEPARATOR ).append( record.get( Record.FILE_EXTENSION ) );
166         }
167         return sb.toString();
168     }
169 
170     /**
171      * Helper to put a value from source map into target map, if not null.
172      */
173     private static void putIfNotNull( final String source, final Map<String, String> target, final String targetName )
174     {
175         if ( source != null )
176         {
177             target.put( targetName, source );
178         }
179     }
180 
181     /**
182      * Helper to put a {@link Long} value from source map into target map, if not null.
183      */
184     private static void putIfNotNullTS( final Long source, final Map<String, String> target, final String targetName )
185     {
186         if ( source != null )
187         {
188             target.put( targetName, String.valueOf( source ) );
189         }
190     }
191 
192     /**
193      * Helper to put a array value from source map into target map joined with {@link Utils#FIELD_SEPARATOR}, if not
194      * null.
195      */
196     private static void putIfNotNullAsStringArray( final String[] source, final Map<String, String> target,
197                                                    final String targetName )
198     {
199         if ( source != null && source.length > 0 )
200         {
201             StringBuilder sb = new StringBuilder();
202             sb.append( source[0] );
203             for ( int i = 1; i < source.length; i++ )
204             {
205                 sb.append( FIELD_SEPARATOR ).append( source[i] );
206             }
207             target.put( targetName, sb.toString() );
208         }
209     }
210 }